/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef NDK_INCLUDE_NATIVE_VSYNC_H_
#define NDK_INCLUDE_NATIVE_VSYNC_H_

/**
 * @addtogroup NativeVsync
 * @{
 *
 * @brief Provides the capabilities of native virtual synchronization (VSync).
 *
 * @syscap SystemCapability.Graphic.Graphic2D.NativeVsync
 * @since 9
 * @version 1.0
 */

/**
 * @file native_vsync.h
 *
 * @brief Declares the functions for obtaining and using <b>NativeVSync</b>.
 *
 * @library libnative_vsync.so
 * @since 9
 * @version 1.0
 */

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief Provides the declaration of an <b>OH_NativeVSync</b> struct.
 * @since 9
 */
struct OH_NativeVSync;

/**
 * @brief Enumerates the error codes.
 * @since 12
 */
typedef enum OHNativeErrorCode {
    /** The operation is successful. */
    NATIVE_ERROR_OK = 0,
    /**
     * An error occurs during memory manipulation.
     * @since 14
     */
    NATIVE_ERROR_MEM_OPERATION_ERROR = 30001000,
    /** An input parameter is invalid. */
    NATIVE_ERROR_INVALID_ARGUMENTS = 40001000,
    /** You do not have the permission to perform the operation. */
    NATIVE_ERROR_NO_PERMISSION = 40301000,
    /** No buffer is available. */
    NATIVE_ERROR_NO_BUFFER = 40601000,
    /** The consumer does not exist. */
    NATIVE_ERROR_NO_CONSUMER = 41202000,
    /** Not initialized. */
    NATIVE_ERROR_NOT_INIT = 41203000,
    /** The consumer is connected. */
    NATIVE_ERROR_CONSUMER_CONNECTED = 41206000,
    /** The buffer status does not meet the expectation. */
    NATIVE_ERROR_BUFFER_STATE_INVALID = 41207000,
    /** The buffer is already in the buffer queue. */
    NATIVE_ERROR_BUFFER_IN_CACHE = 41208000,
    /** The queue is full. */
    NATIVE_ERROR_BUFFER_QUEUE_FULL = 41209000,
    /** The buffer is not in the buffer queue. */
    NATIVE_ERROR_BUFFER_NOT_IN_CACHE = 41210000,
    /** The consumer is disconnected. */
    NATIVE_ERROR_CONSUMER_DISCONNECTED = 41211000,
    /** No listener is registered on the consumer side. */
    NATIVE_ERROR_CONSUMER_NO_LISTENER_REGISTERED = 41212000,
    /** The device or platform does not support the operation. */
    NATIVE_ERROR_UNSUPPORTED = 50102000,
    /** Unknown error. Check the log. */
    NATIVE_ERROR_UNKNOWN = 50002000,
    /** Failed to call the HDI. */
    NATIVE_ERROR_HDI_ERROR = 50007000,
    /** Cross-process communication failed. */
    NATIVE_ERROR_BINDER_ERROR = 50401000,
    /** The EGL environment is abnormal. */
    NATIVE_ERROR_EGL_STATE_UNKNOWN = 60001000,
    /** Failed to call the EGL APIs. */
    NATIVE_ERROR_EGL_API_FAILED = 60002000,
} OHNativeErrorCode;

/**
 * @brief Provides the declaration of an <b>OH_NativeVSync</b> struct.
 * @since 9
 */
typedef struct OH_NativeVSync OH_NativeVSync;

/**
 * @brief Defines the pointer to a VSync callback function.
 *
 * @syscap SystemCapability.Graphic.Graphic2D.NativeVsync
 * @param timestamp System timestamp obtained by VSync using <b>CLOCK_MONOTONIC</b>, in nanoseconds.
 * @param data Custom data.
 * @since 9
 * @version 1.0
 */
typedef void (*OH_NativeVSync_FrameCallback)(long long timestamp, void *data);

/**
 * @brief Creates an <b>OH_NativeVSync</b> instance.
 * A new <b>OH_NativeVSync</b> instance is created each time this function is called.
 * This function must be used in pair with {@link OH_NativeVSync_Destroy}. Otherwise, memory leak occurs. \n
 *
 * @syscap SystemCapability.Graphic.Graphic2D.NativeVsync
 * @param name Pointer to the name that associates with an <b>OH_NativeVSync</b> instance.
 * @param length Length of the name.
 * @return Returns the pointer to an <b>OH_NativeVSync</b> instance.
 * @since 9
 * @version 1.0
 */
OH_NativeVSync* OH_NativeVSync_Create(const char* name, unsigned int length);

/**
 * @brief Creates an <b>OH_NativeVSync</b> instance to bind with a window.
 * A new <b>OH_NativeVSync</b> instance is created each time this function is called.
 *
 * @syscap SystemCapability.Graphic.Graphic2D.NativeVsync
 * @param windowID Window ID, which is the index identifier of the window child process and
 * can be obtained through {@link OH_NativeWindow_GetSurfaceId}.
 * @param name Pointer to the name that associates with an <b>OH_NativeVSync</b> instance.
 * @param length Length of the name.
 * @return Returns the pointer to an <b>OH_NativeVSync</b> instance.
 * @since 14
 * @version 1.0
 */
OH_NativeVSync* OH_NativeVSync_Create_ForAssociatedWindow(uint64_t windowID, const char* name, unsigned int length);

/**
 * @brief Destroys an <b>OH_NativeVSync</b> instance.
 * Once the <b>OH_NativeVSync</b> pointer is destroyed, it must not be used to prevent dangling pointer problems.
 * Pay special attention to the management of the <b>OH_NativeVSync</b> pointer in concurrent multithreaded scenarios.
 *
 * @syscap SystemCapability.Graphic.Graphic2D.NativeVsync
 * @param nativeVsync Pointer to an <b>OH_NativeVSync</b> instance.
 * @since 9
 * @version 1.0
 */
void OH_NativeVSync_Destroy(OH_NativeVSync* nativeVsync);

/**
 * @brief Requests the next VSync signal. When the signal arrives, a callback function is invoked.
 * If this API is called for multiple times in the same frame, only the last callback function is invoked.
 *
 * @syscap SystemCapability.Graphic.Graphic2D.NativeVsync
 * @param nativeVsync Pointer to an <b>OH_NativeVSync</b> instance.
 * @param callback Function pointer of the <b>OH_NativeVSync_FrameCallback</b> type.
 * This function pointer will be called when the next VSync signal arrives.
 * @param data Pointer to the custom data struct. The type is void*.
 * @return Returns <b>0</b> if the operation is successful;
 * returns an error code defined in {@link OHNativeErrorCode} otherwise.
 * @since 9
 * @version 1.0
 */
int OH_NativeVSync_RequestFrame(OH_NativeVSync* nativeVsync, OH_NativeVSync_FrameCallback callback, void* data);

/**
 * @brief Requests the next VSync signal. When the signal arrives, a callback function is invoked.
 * If this API is called for multiple times in the same frame, every callback function is invoked.
 *
 * @syscap SystemCapability.Graphic.Graphic2D.NativeVsync
 * @param nativeVsync Pointer to an <b>OH_NativeVSync</b> instance.
 * @param callback Function pointer of the <b>OH_NativeVSync_FrameCallback</b> type.
 * This function pointer will be called when the next VSync signal arrives.
 * @param data Pointer to the custom data struct. The type is void*.
 * @return Returns <b>0</b> if the operation is successful;
 * returns an error code defined in {@link OHNativeErrorCode} otherwise.
 * @since 12
 * @version 1.0
 */
int OH_NativeVSync_RequestFrameWithMultiCallback(
    OH_NativeVSync* nativeVsync, OH_NativeVSync_FrameCallback callback, void* data);

/**
 * @brief Obtains the VSync period.
 * The VSync period is refreshed only when the <b>OH_NativeVSync_FrameCallback</b> callback is received
 * following a request for a VSync signal via <b>OH_NativeVSync_RequestFrame</b>.
 * To obtain the VSync period for the first time using this function,
 * you need to call <b>OH_NativeVSync_RequestFrame</b> to request a VSync signal.
 * Once the <b>OH_NativeVSync_FrameCallback</b> callback is received, the vsync period can be obtained.
 *
 * @syscap SystemCapability.Graphic.Graphic2D.NativeVsync
 * @param nativeVsync Pointer to an <b>OH_NativeVSync</b> instance.
 * @param period Pointer to the VSync period.
 * @return Returns <b>0</b> if the operation is successful;
 * returns an error code defined in {@link OHNativeErrorCode} otherwise.
 * @since 10
 * @version 1.0
 */
int OH_NativeVSync_GetPeriod(OH_NativeVSync* nativeVsync, long long* period);

/**
 * @brief Enables DVSync to improve the smoothness of self-drawing animations.
 * DVSync, short for Decoupled VSync, is a frame timing management policy that is decoupled from the hardware's VSync.
 * DVSync drives the early rendering of upcoming animation frames by sending VSync signals with future timestamps.
 * These frames are stored in a frame buffer queue.
 * This helps DVSync reduce potential frame drop and therefore enhances the smoothness of animations.
 * DVSync requires free self-drawing frame buffers to store these pre-rendered animation frames.
 * Therefore, you must ensure that at least one free frame buffer is available. Otherwise, do not enable DVSync.
 * After DVSync is enabled, you must correctly respond to the early VSync signals and request the subsequent VSync
 * after the animation frame associated with the previous VSync is complete.
 * In addition, the self-drawing frames must carry timestamps that align with VSync.
 * After the animation ends, disable DVSync.
 * On a platform that does not support DVSync or if another application has enabled DVSync,
 * the attempt to enable it will not take effect, and the application still receives normal VSync signals.
 *
 * @syscap SystemCapability.Graphic.Graphic2D.NativeVsync
 * @param nativeVsync Pointer to an <b>OH_NativeVSync</b> instance.
 * @param enable Whether to enable DVSync.
 * The value <b>true</b> means to enable DVSync, and <b>false</b> means the opposite.
 * @return Returns <b>0</b> if the operation is successful;
 * returns an error code defined in {@link OHNativeErrorCode} otherwise.
 * @since 14
 * @version 1.0
 */
int OH_NativeVSync_DVSyncSwitch(OH_NativeVSync* nativeVsync, bool enable);
#ifdef __cplusplus
}
#endif

#endif
